import { AluRadiusMeta, CreateMeta, HoleMeta } from '@/model/meta/MetaClass';
import earcut from 'earcut';
import { Path, Quaternion, Vector2, Vector3 } from 'three';


/** 角铝的模型构造*/
export default class AluGeoUtil {

    private constructor() { };

    /** 获得一系列的洞点数据*/
    static createHoleMeta(m: HoleMeta): Array<Path> {
        let hole = [];
        if (m && m.hs) {
            for (let item of m.hs) {
                let path = new Path();
                let x = m.dir == "x" ? item : m.x;
                let y = m.dir == "x" ? m.x : item;

                path.moveTo(x, y).absarc(x, y, m.r, 0.0, 2 * Math.PI, false);
                hole.push(path);
            }

        }

        return hole;
    }


    /** 创建一个前后面带洞的板*/
    static createBoardWithHole(c: CreateMeta): GeometryReturnMeta<Array<any>> {
        let vec = [];
        let indics = [];
        let holePoints = [];
        let holePoints2 = [];
        let holeIndex = null;

        let holePath = (c.holeMeta && c.holeMeta.path) ?? this.createHoleMeta(c.holeMeta);


        if (holePath.length > 0) {
            holeIndex = [];
            let curr = c.f.length / 3;
            let ii = 0;
            for (let hole of holePath) {

                holeIndex.push(curr);

                let v2s = hole.getPoints(16);
                for (let v2 of v2s) {
                    holePoints.push(v2.x, v2.y, c.b[2]);
                    holePoints2.push(v2.x, v2.y, c.f[2]);
                }

                curr += v2s.length;
                // console.log(ii);
                // ii++;

                // if(ii++ == 4 ){
                //     break;
                // }

            }
        }

        //合并
        if (c.holeMeta && c.holeMeta.extra) {
            holeIndex = holeIndex ?? [];
            let curr = c.f.length / 3 + holePoints.length / 3;
            for (let item of c.holeMeta.extra) {

                holeIndex.push(curr);

                let bh = item[0];
                let fh = item[1];
                holePoints.push(...bh);
                holePoints2.push(...fh);

                curr += bh.length / 3;
            }
        }



        //前面
        let tp = c.f.concat(holePoints2);
        let ins = earcut(tp, holeIndex, 3)
        vec.push(...tp);
        indics.push(...ins);

        //背面
        tp = c.b.concat(holePoints);
        ins = earcut(tp, holeIndex, 3);
        ins = ins.reverse();
        indics.push(...ins.map((value) => { value += vec.length / 3; return value }));
        vec.push(...tp);

        let n = vec.length / 3;
        //侧面
        for (let i: number = 0, j: number = c.f.length - 3; i < c.f.length; i += 3) {
            // let j = i + 3;
            vec.push(c.f[i], c.f[i + 1], c.f[i + 2]);  //0
            vec.push(c.f[j], c.f[j + 1], c.f[j + 2]);  //1

            vec.push(c.b[i], c.b[i + 1], c.b[i + 2]);   //2
            vec.push(c.b[j], c.b[j + 1], c.b[j + 2]);   //3

            indics.push(n + 2, n, n + 1);
            indics.push(n + 1, n + 3, n + 2);

            j = i;
            n += 4;
        }

        return {
            vertices: vec,
            indices: indics,
            meshface: []
        }
    }
    

    /** 获取二段弧路径
     *  x x上的点
     *  y y上的点
     *  t 内弧与外弧的半径差
     *  r 半径
     *  return 交x轴与y轴的两段弧路径点
    */
    static getRadiusPath(x: number, y: number, t: number, r: number) {

        let c = this.toCircleCenter(x, y, r, t);

        let seg = ~~(r * 2 * c.o_arc_deg / Math.PI);

        let a = this.circlePath(c.center.x, c.center.y, r, c.o_arc_deg, c.o_arc_r_deg, seg);
        let b = this.circlePath(c.center.x, c.center.y, c.inner_arc_radius, c.i_arc_deg, c.i_arc_r_deg, seg);

        return [a, b];
    }


    /** 一个弧体
     * x x上的点
     * y y上的点
     * t 两个弧之间的厚度
     * l 弧宽
     * r 弧半径
    */
    static createSellipse(x: number, y: number, t: number = 100, l: number = 600, r: number = 100): GeometryReturnMeta<Array<any>> {
        let vec = [];
        let indics = [];

        let c = this.toCircleCenter(x, y, r, t);
        let a = this.circlePath(c.center.x, c.center.y, r, c.o_arc_deg, c.o_arc_r_deg);
        let b = this.circlePath(c.center.x, c.center.y, c.inner_arc_radius, c.i_arc_deg, c.i_arc_r_deg);

        //外弧面
        let aa = this.ellipse(a, l);
        indics.push(...aa.indices.map((value) => { value += vec.length / 3; return value; }));
        vec.push(...aa.vertices);

        let bb = this.ellipse(b, l);
        indics.push(...bb.indices.reverse().map((value) => { value += vec.length / 3; return value; }));
        vec.push(...bb.vertices);

        //2个侧面
        let no = vec.length / 3;

        for (let i: number = 0; i < a.length - 3; i += 3) {
            //绕y轴旋转90度处理 x = 0, z = x;
            //绕x轴旋转90度处理 y = -z, z = y;
            let a1 = [a[i + 2], -a[i], a[i + 1]];
            let a2 = [a[i + 5], -a[i + 3], a[i + 4]];

            let b1 = [b[i + 2], -b[i], b[i + 1]];
            let b2 = [b[i + 5], -b[i + 3], b[i + 4]];

            vec.push(...a1, ...a2, ...b1, ...b2);
            indics.push(no, no + 1, no + 2);
            indics.push(no + 2, no + 1, no + 3);
            no += 4;


            let a3 = [a[i + 2] + l, -a[i], a[i + 1]];
            let a4 = [a[i + 5] + l, -a[i + 3], a[i + 4]];

            let b3 = [b[i + 2] + l, -b[i], b[i + 1]];
            let b4 = [b[i + 5] + l, -b[i + 3], b[i + 4]];

            vec.push(...a3, ...a4, ...b3, ...b4);
            indics.push(no + 1, no, no + 2);
            indics.push(no + 2, no + 3, no + 1);
            no += 4;
        }

        return {
            vertices: vec,
            indices: indics,
            meshface: []
        }
    }


    /** 弧面
     *  l == 弧宽
    */
    static ellipse(ps: Array<any>, l: number = 600): GeometryReturnMeta<Array<any>> {
        let vec = [];
        let indics = [];
        let no = 0;


        for (let i: number = 0; i <= ps.length - 6; i += 3) {
            //绕y轴旋转90度处理 x = 0, z = x;
            //绕x轴旋转90度处理 y = -z, z = y;

            vec.push(0, -ps[i], ps[i + 1]);
            vec.push(l, -ps[i], ps[i + 1]);

            vec.push(0, -ps[i + 3], ps[i + 4]);
            vec.push(l, -ps[i + 3], ps[i + 4]);

            indics.push(no + 1, no + 3, no);
            indics.push(no, no + 3, no + 2);
            no += 4;
        }

        return {
            vertices: vec,
            indices: indics,
            meshface: []
        }
    }

    /** 弧线路径
     *  x, y 圆心
     *  r 半径
     *  d 弧度
     *  td 旋转弧度
    */
    static circlePath(x, y, r, d, td, seg = 64): Array<number> {
        let offset = new Vector3(x, y, 0);

        let path = new Path();
        path.absarc(x, y, r, 0, d, false);
        let points = path.getPoints(seg);
        let b = [];

        let q = new Quaternion();
        q.setFromAxisAngle(new Vector3(0, 0, 1), td);

        let v3 = new Vector3();
        for (let v of points) {
            v3.set(v.x, v.y, 0).sub(offset).applyQuaternion(q);
            b.push(...v3.add(offset).toArray());
        }

        return b;
    }


    /** 计算一个距离xy轴的两段圆弧的参数
     *  x x轴的偏移
     *  y y轴的偏移
     *  r 绝对半径
     *  t 内弧与外弧的偏移量
     *  
     * return AluRadiusMeta
    */
    static toCircleCenter(x, y, r, t = 100): AluRadiusMeta {

        let nodeA = new Vector2(x, 0);
        let nodeB = new Vector2(0, y);
        //中心点
        let nodeC = new Vector2(0.5 * x, 0.5 * y);
        //垂线方向
        let n2 = new Vector2(-y, -x); //垂线方向

        //圆心
        let xl = (- x) * (- x) + y * y;
        let dis = Math.sqrt(r * r - (xl / 4));
        let nd = n2.normalize().multiplyScalar(dis).add(nodeC);

        //外弧角
        let a_d_nd = nodeA.clone().sub(nd);
        let a_nd = nodeA.clone().sub(nd).normalize();

        let b_d_nd = nodeB.clone().sub(nd);
        let b_nd = nodeB.clone().sub(nd).normalize();
        let cos = a_nd.dot(b_nd);
        let deg = Math.acos(cos);

        //画弧后旋转的角度
        let rd = Math.atan(a_nd.y / a_nd.x);



        //内弧两点
        let i_rp = (r - t) * (r - t);
        let yy = a_d_nd.y;
        let x_rp = i_rp - yy * yy;
        let xx = Math.sqrt(x_rp);
        let xxx = x - (a_d_nd.x - xx);

        let aa = new Vector2(xxx, 0);

        xx = b_d_nd.x;
        let y_rp = i_rp - xx * xx;
        let yyy = Math.sqrt(y_rp);
        let yyyy = y - (b_d_nd.y - yyy);

        let bb = new Vector2(0, yyyy);

        //内弧半径
        let aa_nd = aa.sub(nd);
        let rr = aa_nd.length();
        aa_nd.normalize();
        let bb_nd = bb.sub(nd).normalize();

        //内弧角
        let cos1 = Math.acos(aa_nd.dot(bb_nd));
        //画内弧后旋转的角度
        let rd2 = Math.atan(aa_nd.y / aa_nd.x);

        return new AluRadiusMeta(nd, deg, rd, rr, cos1, rd2);
    }


    /** 过滤洞的数据
     *  @params l总长
     *  @params h洞的数组
     *  @params empty
    */
    static filterHole(l: number, h: Array<number>, empty: number = 0) {
        return h.filter((value) => {
            return value <= (l - empty);
        })
    }

    /** 过滤洞的数据
     *  @params l总长
     *  @params h洞的数组
     *  @params empty
    */
    static filterHoleLess(less: number, h: Array<number>, empty: number = 0) {
        return h.filter((value) => {
            return value >= (less + empty);
        })
    }


    /** 过滤洞的数据
     *  @params min
     *  @params max
     *  @params h洞的数组
     *  @params empty
    */
    static filterHoleLessMore(min: number, max: number, h: Array<number>) {
        return h.filter((value) => {
            return value >= min && value <= max;
        })
    }

    /** 过滤洞的数据
     *  @params min
     *  @params max
     *  @params h洞的数组
     *  @params empty
    */
    static reverseHole(end: number, h: Array<number>) {
        return h.map((value) => {
            return value = end - value;
        })
    }


    /** 
     * 计算两块板相交（ x, z）的落点
    */
    static getEquinox(bw1: number, bw2: number, angle: number): Record<"x" | "z", any> {
        // let angle = +data.angle1;
        // let b_w = +data.BKH;
        // let l_w = +data.BKH;


        //转锐角？
        let mr = (-1 * angle) - (-90);

        let rr = mr / 180 * Math.PI;
        let tr = Math.abs(mr) == 90 ? 0 : Math.tan(rr);
        let cr = Math.cos(rr);

        //x /cr + h * tr
        let x = (Math.abs(mr) == 90 ? 0 : bw1 / cr) + bw2 * tr;
        let y = (Math.abs(mr) == 90 ? 0 : bw2 / cr) + bw1 * tr;



        return {
            x: x,
            z: y
        }
    }
}